using System.ComponentModel;
using System.Security;
using System.Security.AccessControl;
using System.Xml.Serialization;
using uTILLIty.Rave.Contract.Configuration;

namespace uTILLIty.Rave.Contract.StorageAdapter
{
	/// <summary>
	/// A helper object holding all meta- and context-data during <see cref="SecurityContext"/>
	/// merging
	/// </summary>
	public class SecurityEntryContext
	{
		/// <summary>
		/// Creates a new instance of the <see cref="SecurityEntryContext"/>
		/// </summary>
		/// <param name="storageMember">The member-information of the permission-holder</param>
		/// <param name="currentRights">The issued rights</param>
		public SecurityEntryContext(StorageMember storageMember, string currentRights)
		{
			StorageMember = storageMember;
			CurrentRights = currentRights;
			Action = SecurityEntryAction.Nothing;
			AccessControlType = AccessControlType.Allow;
			CurrentInheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
			CurrentPropagationFlags = PropagationFlags.None;
		}

		/// <summary>
		/// Creates a new instance of the <see cref="SecurityEntryContext"/>
		/// </summary>
		public SecurityEntryContext(StorageMember storageMember, InheritanceFlags currentInheritanceFlags, PropagationFlags currentPropagationFlags) : this(storageMember, "")
		{
			CurrentInheritanceFlags = currentInheritanceFlags;
			CurrentPropagationFlags = currentPropagationFlags;
		}

		/// <summary>
		/// The member-information of the permission-holder
		/// </summary>
		public StorageMember StorageMember { get; set; }

		/// <summary>
		/// The issued rights
		/// </summary>
		/// <seealso cref="Contract.Configuration.SecurityEntry.Rights"/>
		public string CurrentRights { get; set; }

		/// <summary>
		/// The type of <see cref="CurrentRights">rights</see>
		/// </summary>
		[DefaultValue(AccessControlType.Allow), XmlAttribute("type")]
		public AccessControlType AccessControlType { get; set; }

		/// <summary>
		/// The ACL entry/object - supplied to the <see cref="IStorageAdapter"/>
		/// for processing changes
		/// </summary>
		public object AclEntry { get; set; }

		/// <summary>
		/// Inheritance flags specify the semantics of inheritance for access control entries (ACEs).
		/// </summary>
		[DefaultValue(InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit), XmlAttribute("inheritanceFlags")]
		public InheritanceFlags CurrentInheritanceFlags { get; set; }

		/// <summary>
		/// Progagation flags specify how the ACL is handled by child-elements
		/// </summary>
		[DefaultValue(PropagationFlags.None), XmlAttribute("propagationFlags")]
		public PropagationFlags CurrentPropagationFlags { get; set; }

		/// <summary>
		/// The <see cref="Contract.Configuration.SecurityEntry"/> from the configuration
		/// holding all meta-data to be applied
		/// </summary>
		public SecurityEntry TemplateSecurityEntry { get; set; }

		/// <summary>
		/// The action to be applied to the <see cref="AclEntry"/>
		/// </summary>
		public SecurityEntryAction Action { get; set; }

		/// <summary>
		/// Indicates that this ACL-Entry has been processed and thus resembles an entry which has been
		/// specified in the configuration
		/// </summary>
		public bool Touched { get; set; }

		/// <summary>
		/// Returns a summary for this instance
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			return string.Format("{0}: {1}", StorageMember, TemplateSecurityEntry);
		}

		#region Equality members

		/// <summary>
		/// Checks equality for <see cref="StorageMember"/>, <see cref="AccessControlType"/>, <see cref="CurrentInheritanceFlags"/>, 
		/// and <see cref="CurrentPropagationFlags"/>
		/// </summary>
		protected bool Equals(SecurityEntryContext other)
		{
			return Equals(StorageMember, other.StorageMember) 
				&& AccessControlType.Equals(other.AccessControlType)
				&& CurrentInheritanceFlags.Equals(other.CurrentInheritanceFlags) 
				&& CurrentPropagationFlags.Equals(other.CurrentPropagationFlags);
		}

		/// <summary>
		/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <returns>
		/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
		/// </returns>
		/// <param name="obj">The object to compare with the current object. </param><filterpriority>2</filterpriority>
		public override bool Equals(object obj)
		{
			if (ReferenceEquals(null, obj)) return false;
			if (ReferenceEquals(this, obj)) return true;
			if (obj.GetType() != this.GetType()) return false;
			return Equals((SecurityEntryContext)obj);
		}

		/// <summary>
		/// Serves as a hash function for a particular type. 
		/// </summary>
		/// <returns>
		/// A hash code for the current <see cref="T:System.Object"/>.
		/// </returns>
		/// <filterpriority>2</filterpriority>
		public override int GetHashCode()
		{
			unchecked
			{
				int hashCode = (StorageMember != null ? StorageMember.GetHashCode() : 0);
				hashCode = (hashCode * 397) ^ AccessControlType.GetHashCode();
				hashCode = (hashCode * 397) ^ CurrentInheritanceFlags.GetHashCode();
				hashCode = (hashCode * 397) ^ CurrentPropagationFlags.GetHashCode();
				return hashCode;
			}
		}

		#endregion
	}
}